package com.zjl.学习.第06章_块步骤_读操作写.B_ItemProcessor处理;

import com.zjl.springbatch.util.OutColour;
import com.zjl.学习.第06章_块步骤_读操作写.User;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.adapter.ItemProcessorAdapter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.support.CompositeItemProcessor;
import org.springframework.batch.item.support.ScriptItemProcessor;
import org.springframework.batch.item.validator.BeanValidatingItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
 * 前面我们多次讲过，居于块的读与写，中间还夹着一个ItemProcessor 条目处理。
 * 当我们通过ItemReader 将数据读取出来之后，你面临2个选择：
 *      1>直接将数据转向输出
 *      2>对读入的数据进行再加工。
 *
 * 如果选择第一种，那ItemProcessor 可以不用出现，如果选择第二种，就需要引入ItemProcessor 条目处理组件啦。
 * Spring Batch 为Processor 提供默认的处理器与自定义处理器2种模式以满足各种需求。
 *
 *
 */
@SpringBootApplication
@EnableBatchProcessing
public class B0_ItemProcessor {
    @Autowired//@EnableBatchProcessing 这个注解帮你从 spring batch 的配置文件中加载了
    private JobLauncher jobLauncher;//Job 启动器
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Bean
    public FlatFileItemReader<User> itemReaderB(){
        return new FlatFileItemReaderBuilder<User>()
                .name("itemReaderB")
                .resource(new ClassPathResource("item/user校验.txt"))  //指定读取的文件
                .delimited().delimiter("#")  //读取出一行数据，该如何分割数据，默认以,分割，当前使用#号分割
                .names("id", "name", "age")//给分割后数据打name标记，后续跟User对象属性进行映射
                .targetType(User.class)      //读取出一行数据封装成什么对象
                .build();
    }
    @Bean//校验器处理器  使用spring的 Validating
    public BeanValidatingItemProcessor<User> itemProcessorValidating(){
        BeanValidatingItemProcessor<User> beanValidatingItemProcessor = new BeanValidatingItemProcessor<>();
        beanValidatingItemProcessor.setFilter(true);  //不满足条件丢弃数据

        return beanValidatingItemProcessor;
    }

    @Autowired
    private UserServiceImpl userService;
    @Bean//使用指定的方法
    public ItemProcessorAdapter<User, User> itemProcessorAdapter(){
        ItemProcessorAdapter<User, User> adapter = new ItemProcessorAdapter<>();
        adapter.setTargetObject(userService);//执行此类
        adapter.setTargetMethod("toUpperCase");//此方法

        return adapter;
    }

    @Bean//使用 js 脚本实现校验
    public ScriptItemProcessor<User, User> scriptItemProcessor(){
        ScriptItemProcessor<User, User> scriptItemProcessor = new ScriptItemProcessor();
        scriptItemProcessor.setScript(new ClassPathResource("item/userScript.js"));
        return scriptItemProcessor;
    }
    @Bean //组合校验
    public CompositeItemProcessor<User, User>  compositeItemProcessor(){
        CompositeItemProcessor<User, User> compositeItemProcessor = new CompositeItemProcessor<>();
        compositeItemProcessor.setDelegates(Arrays.asList(
                itemProcessorValidating(), //放入三个校验器  name为空的删除
                itemProcessorAdapter(),//放入三个校验器      name变大写
                scriptItemProcessor()//放入三个校验器        name字段添加后缀
        ));
        return  compositeItemProcessor;
    }

    @Autowired
    private MyItemProcessor myItemProcessor;//自定义处理器
    @Bean
    public ItemWriter<User> itemWriterB(){
        return new ItemWriter<User>() {
            @Override
            public void write(List<? extends User> items) throws Exception {
                OutColour.out.printlnRed(items + "个数：" + items.size());
            }
        };
    }
    @Bean
    public Step stepItemB() throws Exception {
        return stepBuilderFactory.get("stepItemB")
                .<User, User>chunk(2)//执行多少次读处理，再进行写
                .reader(itemReaderB())//读
                .processor(itemProcessorValidating())//处理  使用 spring 的 Validating 校验器，校验
                .processor(itemProcessorAdapter())//处理  使用 自定义逻辑的校验器
                .processor(scriptItemProcessor())//处理  使用 脚本
                .processor(compositeItemProcessor())//处理  使用  组合校验
                .processor(myItemProcessor)//自定义处理器
                .writer(itemWriterB())//写
                .build()
                ;
    }
    @Bean
    public Job jobItemB() throws Exception {
        return jobBuilderFactory.get("jobItemB")
                .start(stepItemB())
                .incrementer(new RunIdIncrementer())
                .build();
    }

    public static void main(String[] args) {
        System.setProperty("spring.profiles.active","01");//  同理 --spring.profiles.active=xxx
        SpringApplication.run(B0_ItemProcessor.class, args);
        System.out.println("***********启动完毕**当前编码:" + Charset.defaultCharset().name() + "****************");

    }
}
